package com.demo.function.spring.state.machine.service;

import com.alibaba.fastjson.JSON;
import com.demo.model.ApprovalFile;
import com.demo.function.spring.state.machine.StateMachineConfig;
import com.demo.function.spring.state.machine.StateMachineFactoryConfig;
import com.demo.function.spring.state.machine.event.Event;
import com.demo.function.spring.state.machine.status.Status;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.StateMachineSystemConstants;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 状态机服务
 */
@Slf4j
@Service
public class StateMachineService {

    private AtomicInteger integer = new AtomicInteger();

    /**
     * 注入状态机，对应的类{@link StateMachineConfig}
     */
    @Resource
    private StateMachine<Status, Event> stateMachine;

    /**
     * 注入状态机工厂，对应的类{@link StateMachineFactoryConfig}
     */
    @Resource
    private StateMachineFactory<Status, Event> orderStateMachineFactory;

    @Resource(name = "approvalFilePersister")
    private StateMachinePersister<Status, Event, ApprovalFile> stateMachinePersister;

    public void machineStart() {
        start(stateMachine);
    }

    public void machineFactoryStart() {
        StateMachine<Status, Event> stateMachine =
                orderStateMachineFactory.getStateMachine(StateMachineSystemConstants.DEFAULT_ID_STATEMACHINEFACTORY);

        start(stateMachine);
    }

    /**
     * 将状态机初始状态改为待审核，并进行下一步状态处理
     * @throws Exception
     */
    public void changeMachineStatus() throws Exception {
        ApprovalFile file = new ApprovalFile();
        file.setStatus(Status.AUDIT);

        stateMachinePersister.restore(stateMachine, file);

        Message<Event> message = wrapperMessage(Event.PASS, file, 0);
        stateMachine.sendEvent(message);
    }

    private void start(StateMachine<Status, Event> stateMachine) {
        int tmp = integer.incrementAndGet();
        ApprovalFile file = new ApprovalFile();
        Message<Event> message = wrapperMessage(Event.SAVE, file, tmp);
        log.info("message ={}", message);
        stateMachine.start();
        stateMachine.sendEvent(message);
        log.info("number = {}, 状态 = {}", tmp, JSON.toJSONString(stateMachine.getState()));

        message = wrapperMessage(Event.UN_PASS, file, tmp);
        stateMachine.sendEvent(message);
        log.info("number = {}, 状态 = {}", tmp, JSON.toJSONString(stateMachine.getState()));

        message = wrapperMessage(Event.SAVE, file, tmp);
        stateMachine.sendEvent(message);
        log.info("number = {}, 状态 = {}", tmp, JSON.toJSONString(stateMachine.getState()));

        message = wrapperMessage(Event.PASS, file, tmp);
        stateMachine.sendEvent(message);
        log.info("number = {}, 状态 = {}", tmp, JSON.toJSONString(stateMachine.getState()));

        stateMachine.stop();
        log.info("状态机执行完毕");
    }

    private Message<Event> wrapperMessage(Event event, ApprovalFile file, int number) {
        return MessageBuilder.withPayload(event)
                .setHeader("file", file)
                .setHeader("number", number)
                .build();
    }
}
